package com.iotcomm.server;

import com.iotcomm.listener.MessageListener;
import com.iotcomm.protocol.Message;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 服务器端消息处理器
 * 处理客户端连接、消息接收等事件
 */
public class ServerHandler extends SimpleChannelInboundHandler<Message> {
    private static final Logger logger = LoggerFactory.getLogger(ServerHandler.class);
    
    // 存储所有活跃的客户端连接
    private static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    
    private final MessageListener messageListener;
    
    /**
     * 构造函数
     * @param messageListener 消息监听器
     */
    public ServerHandler(MessageListener messageListener) {
        this.messageListener = messageListener;
    }
    
    /**
     * 客户端连接时触发
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        String channelId = ctx.channel().id().asShortText();
        channels.add(ctx.channel());
        
        logger.info("客户端连接: {}", channelId);
        
        if (messageListener != null) {
            messageListener.onClientConnected(channelId);
        }
    }
    
    /**
     * 客户端断开连接时触发
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        String channelId = ctx.channel().id().asShortText();
        channels.remove(ctx.channel());
        
        logger.info("客户端断开连接: {}", channelId);
        
        if (messageListener != null) {
            // 从channel属性中获取用户名
            String username = (String) ctx.channel().attr(io.netty.util.AttributeKey.valueOf("username")).get();
            messageListener.onClientDisconnected(channelId, username);
        }
    }
    
    /**
     * 接收到消息时触发
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Message msg) {
        String channelId = ctx.channel().id().asShortText();
        
        logger.debug("接收到消息: {} from {}", msg, channelId);
        
        // 如果是登录消息，保存用户名到channel属性中
        if (msg.getMessageType() == Message.LOGIN) {
            ctx.channel().attr(io.netty.util.AttributeKey.valueOf("username")).set(msg.getSender());
        }
        
        if (messageListener != null) {
            messageListener.onMessageReceived(msg, channelId);
        }
    }
    
    /**
     * 异常处理
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        String channelId = ctx.channel().id().asShortText();
        
        logger.error("连接异常: {}", channelId, cause);
        
        if (messageListener != null) {
            messageListener.onConnectionError(channelId, cause);
        }
        
        ctx.close();
    }
    
    /**
     * 获取所有活跃的客户端连接
     * @return 客户端连接组
     */
    public static ChannelGroup getChannels() {
        return channels;
    }
    
    /**
     * 向指定通道发送消息
     * @param channelId 通道ID
     * @param message 消息
     */
    public static void sendToChannel(String channelId, Message message) {
        channels.stream()
                .filter(channel -> channel.id().asShortText().equals(channelId))
                .findFirst()
                .ifPresent(channel -> {
                    if (channel.isActive()) {
                        channel.writeAndFlush(message);
                        logger.debug("发送消息到 {}: {}", channelId, message);
                    }
                });
    }
    
    /**
     * 广播消息到所有客户端
     * @param message 消息
     */
    public static void broadcast(Message message) {
        channels.writeAndFlush(message);
        logger.debug("广播消息: {}", message);
    }
    
    /**
     * 广播消息到所有客户端（排除指定通道）
     * @param message 消息
     * @param excludeChannelId 要排除的通道ID
     */
    public static void broadcastExclude(Message message, String excludeChannelId) {
        channels.stream()
                .filter(channel -> !channel.id().asShortText().equals(excludeChannelId))
                .forEach(channel -> {
                    if (channel.isActive()) {
                        channel.writeAndFlush(message);
                    }
                });
        logger.debug("广播消息（排除 {}）: {}", excludeChannelId, message);
    }
}